#include "tools/bitmap.h"
#include "tools/klib.h"

/**
 * 求bit数需要的字节数
 */
inline int bitmap_byte_count(int count)
{
    // 向上取整
    return (count + 8 - 1) / 8;
}

void bitmap_init(bitmap_t *bitmap, uint8_t *bits, int count, int init_bit)
{
    bitmap->bit_count = count;
    bitmap->bits = bits;
    kernel_memset(bitmap->bits, init_bit ? 0xFF : 0x00, bitmap_byte_count(count));
}

int bitmap_get_bit(bitmap_t *bitmap, int index)
{
    return bitmap->bits[index / 8] & (1 << (index % 8)) ? 1 : 0;
}

void bitmap_set_bit(bitmap_t *bitmap, int index, int count, int bit)
{
    for (int i = 0; i < count && index < bitmap->bit_count; i++, index++) {
        if (bit) {
            bitmap->bits[index / 8] |= (1 << (index % 8));
        } else {
            bitmap->bits[index / 8] &= ~(1 << (index % 8));
        }
    }
}

int bitmap_is_set(bitmap_t *bitmap, int index)
{
    return bitmap_get_bit(bitmap, index);
}

/**
 * 分配连续的n个位
 * bit: 待分配的位状态
 */
int bitmap_alloc_nbits(bitmap_t *bitmap, int bit, int count)
{
    for (int i = 0; i < bitmap->bit_count; i++) {
        if (bitmap_get_bit(bitmap, i) != bit) {
            continue;
        }

        int ok_idx = i;
        int cnt = 1;
        for (i = ok_idx + 1; i < bitmap->bit_count && cnt < count; i++) {
            if (bitmap_get_bit(bitmap, i) != bit) {
                break;
            }
            cnt++;
        }

        if (cnt >= count) {
            bitmap_set_bit(bitmap, ok_idx, count, !bit);
            return ok_idx;
        }
    }
    return -1;
}
